package com.filters;

import com.common.util.rsa.RsaKeys;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.netflix.zuul.context.RequestContext;
import com.service.RsaService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Component
public class MyRibbonRoutingFilter extends RibbonRoutingFilter {

	
	public MyRibbonRoutingFilter(ProxyRequestHelper helper,
			RibbonCommandFactory<?> ribbonCommandFactory,
			List<RibbonRequestCustomizer> requestCustomizers) {
		super(helper, ribbonCommandFactory, requestCustomizers);
		// TODO Auto-generated constructor stub
	}

	private static Logger log = LoggerFactory.getLogger(MyRibbonRoutingFilter.class);
	
	@Autowired
	private RsaService rsaService;
	
	@Override
	public String filterType() {
		
		return FilterConstants.ROUTE_TYPE;
	}

	@Override
	public int filterOrder() {
		return FilterConstants.RIBBON_ROUTING_FILTER_ORDER - 1;
	}

	@Override
	public boolean shouldFilter() {

		return true;
	}

	
	
	@Override
	public Object run() {

		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		log.info(String.format("%s >>> %s", request.getMethod(), request
				.getRequestURL().toString()));
		// String data = request.getParameter("data");

		ClientHttpResponse response = null;
		
		BufferedReader br;
		String requestBody = null;
		HashMap params = null;
		byte[] encryptData;
		try {

			// 客户端传的是string对象
			StringBuffer sb = new StringBuffer("");
			String temp;

			br = new BufferedReader(new InputStreamReader(
					(ServletInputStream) request.getInputStream(), "utf-8"));
			while ((temp = br.readLine()) != null) {
				sb.append(temp);
			}

			br.close();
			requestBody = sb.toString();

			System.out.println("rsa加密算法：" + rsaService.getRsaAlgorithm());
			System.out.println("从request中取出来的data：" + requestBody);

			String decryptData = rsaService.RSADecryptDataPEM(requestBody,
					RsaKeys.getServerPrvKeyPkcs8());

			// 客户端传的是byte数组
			// ServletInputStream sis = (ServletInputStream)
			// request.getInputStream();
			// BufferedInputStream bufin = new BufferedInputStream(sis);
			// int buffSize = 1024;
			// ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
			// byte[] temp = new byte[buffSize];
			// int size = 0;
			// while ((size = bufin.read(temp)) != -1) {
			// out.write(temp, 0, size);
			// }
			// bufin.close();
			//
			// encryptData = out.toByteArray();
			// requestBody = new String(encryptData, "utf-8");
			//
			// String decryptData = rsaService.RSADecryptDataBytes(encryptData,
			// RsaKeys.getServerPrvKeyPkcs8());

			System.out.println("解密后的data：" + decryptData);

			// 将解密后的json字符串转换为参数map
			params = new Gson().fromJson(decryptData,
					new TypeToken<HashMap<String, Object>>() {
					}.getType());

			//将参数塞进request
//			ParameterRequestWrapper wrapper = new ParameterRequestWrapper(ctx.getRequest());
//			for (Object key : params.keySet()) {
//				wrapper.addParameter((String) key, params.get(key));
//			}
//			
//			wrapper.addAllParameters(params);
//			wrapper.appendApiNameToUrl((String) params.get("apiName"));
//
//			ctx.setRequest(wrapper);
			
			RibbonCommandContext cmdCtx = this.buildCommandContext(ctx, params);
			
			response = forward(cmdCtx);
			setResponse(response);
			
			//RibbonRoutingFilter r = new RibbonRoutingFilter();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// if(ret.getCode() != RetCode.SUCCESS)
		// {
		// Gson gson = new Gson();
		// String jsonStr = gson.toJson(ret);
		// ctx.setSendZuulResponse(false);
		// ctx.setResponseStatusCode(200);
		//
		// try {
		// ctx.getResponse().getWriter().write(jsonStr);
		// }catch (Exception e){
		// e.printStackTrace();
		// }
		//
		// return null;
		// }

		log.info("ok");
		return response;
	}
	
	protected RibbonCommandContext buildCommandContext(RequestContext context, HashMap extParams) {
		HttpServletRequest request = context.getRequest();

		MultiValueMap<String, String> headers = this.helper
				.buildZuulRequestHeaders(request);
		MultiValueMap<String, String> params = this.helper
				.buildZuulRequestQueryParams(request);
		
		for (Object key : extParams.keySet()) {
			List<String> list = new ArrayList<String>();
			list.add((String) extParams.get(key));
			params.put((String) key, list);
		}
		
		String verb = getVerb(request);
		InputStream requestEntity = getRequestBody(request);
		if (request.getContentLength() < 0 && !verb.equalsIgnoreCase("GET")) {
			context.setChunkedRequestBody();
		}

		String serviceId = (String) context.get(FilterConstants.SERVICE_ID_KEY);
		Boolean retryable = (Boolean) context.get(FilterConstants.RETRYABLE_KEY);

		String uri = this.helper.buildZuulRequestURI(request);

		// remove double slashes
		uri = uri.replace("//", "/");

		long contentLength = request.getContentLengthLong();

		return new RibbonCommandContext(serviceId, verb, uri, retryable, headers, params,
				requestEntity, this.requestCustomizers, contentLength);
	}
}